package com.glink.manage.service.Impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.glink.common.contants.BaseCodeConstants;
import com.glink.common.exception.GeneralSimpleException;
import com.glink.common.util.BaseCommonUtils;
import com.glink.manage.common.CardUtil;
import com.glink.manage.common.Constants;
import com.glink.manage.common.enums.MqttEnum;
import com.glink.manage.domain.ConstructionWorkAccessMonadBean;
import com.glink.manage.domain.TemporaryAdmissionBean;
import com.glink.manage.dto.temporaryadmission.*;
import com.glink.manage.mapper.TemporaryAdmissionMapper;
import com.glink.manage.service.*;
import com.glink.manage.vo.barriergate.PersonSyncDetailInfoVO;
import com.glink.manage.vo.constructionwork.ConstructionWorkListVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionCarBaseVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionCheckWorkVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionPageVO;
import com.glink.manage.vo.temporaryadmission.TemporaryAdmissionPersonBaseVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author  qiushaoshan
 * @since 2025-03-04
 */
@Service
@Slf4j
public class TemporaryAdmissionServiceImpl extends ServiceImpl<TemporaryAdmissionMapper, TemporaryAdmissionBean> implements TemporaryAdmissionService {

    @Autowired
    private UserService userService;
    
    @Autowired
    private OrgService orgService;
    
    @Autowired
    private PersonManageService personManageService;
    
    @Autowired
    private ConstructionWorkService constructionWorkService;
    
    @Autowired
    private ConstructionWorkUnitRelaService constructionWorkUnitRelaService;

    @Autowired
    private BlacklistService blacklistService;

    @Autowired
    private AttachmentService attachmentService;
    
    @Autowired
    private ConstructionWorkAccessMonadService constructionWorkAccessMonadService;

    // 黑名单的年龄标准
    @Value("${blacklist.age.level:60}")
    private Integer blacklistAgeLevel;
    
    /**
     * 新增人员临时准入信息
     *
     * @param dto 临时准入信息
     * @return 临时准入ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String insertPerson(TemporaryAdmissionPersonSaveDTO dto) throws GeneralSimpleException {

        if (StringUtils.isNotBlank(dto.getIdNumber()) && dto.getIdNumber().length() == 18) {
            Date birth = CardUtil.extractBirthDate(dto.getIdNumber());
            // 校验生日是否符合区间
            String msg = checkPersonAgeLimit(dto.getName(), birth);
            if (StringUtils.isNotBlank(msg)) {
                throw new GeneralSimpleException("400068", msg);
            }
        }
        
        // 项目部单位
        boolean department = orgService.checkDepartment();

        TemporaryAdmissionBean temporaryAdmissionBean = new TemporaryAdmissionBean();
        BeanUtils.copyProperties(dto, temporaryAdmissionBean);

        // 人员主键ID
        temporaryAdmissionBean.setObjId(BaseCommonUtils.generateUUID());
        
        // 人员数字ID--临时准入人员ID要和人员表保持一致
        temporaryAdmissionBean.setPersonId(getPersonId(dto.getIdNumber()));
       
        temporaryAdmissionBean.setOrgId(BaseCommonUtils.extractOrdIdByToken());
        
        // 审批单类型--人员
        temporaryAdmissionBean.setType(BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType01);
        boolean status = true;

        // 添加审批单-项目部直接通过
        String accessMonadObjId = null;
        if(department){
            accessMonadObjId = BaseCommonUtils.generateUUID();
            ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = new ConstructionWorkAccessMonadBean();
            constructionWorkAccessMonadBean.setObjId(accessMonadObjId);
            constructionWorkAccessMonadBean.setConstructionWorkObjId(temporaryAdmissionBean.getConstructionWorkObjId());
            constructionWorkAccessMonadBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03);
            constructionWorkAccessMonadBean.setAssociationObjId(temporaryAdmissionBean.getObjId());
            // 当前人员是项目部的人，则无需审批，直接通过
            constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);

            constructionWorkAccessMonadBean.setCycleStart(temporaryAdmissionBean.getCycleStart());
            constructionWorkAccessMonadBean.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
            constructionWorkAccessMonadBean.setCreateUserOrgId(BaseCommonUtils.extractOrdIdByToken());
            status = constructionWorkAccessMonadService.saveBean(constructionWorkAccessMonadBean);
        }
        
        if(status){
            temporaryAdmissionBean.setAccessMonadObjId(accessMonadObjId);
            status = this.save(temporaryAdmissionBean);
            if(status){
                return temporaryAdmissionBean.getObjId();
            }else{
                log.error("人员临时准入信息保存失败");
            }
        }else{
            log.error("人员临时准入审批单保存失败");
        }

        throw new GeneralSimpleException("400062");
    }

    /**
     * 校验生日是否符合区间
     * @param name 人员姓名
     * @param birth 人员生日
     * @return 返回文字说明
     */
    private String checkPersonAgeLimit(String name, Date birth){
        String msg = "";
        if(Objects.nonNull(birth)){
            LocalDate currentDate = LocalDate.now(); // 当前日期
            // 将 Date 转换为 LocalDate
            LocalDate localDate = birth.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            // 计算年龄
            int age = Period.between(localDate, currentDate).getYears();

            // 判断年龄是否超过60岁或小于18岁
            if (age >= blacklistAgeLevel) {
                msg = String.format("人员%s的年龄已经超过了%s岁", name, blacklistAgeLevel);
            } else if (age < 18) {
                msg = String.format("人员%s未成年", name);
            }
        }
        return msg;
    }

    /**
     * 根据身份证号查询人员ID
     * @param card 身份证号
     * @return 人员ID
     */
    private Integer getPersonId(String card){
        Integer personId = null;
        // 人员数字ID--临时准入人员ID要和人员表保持一致
        if(StringUtils.isNotBlank(card)){
            personId = personManageService.findIdByCard(card);
            if(Objects.nonNull(personId)){
                return personId;
            }
        }

        List<TemporaryAdmissionBean> temporaryAdmissionBeanList = this.lambdaQuery().eq(TemporaryAdmissionBean::getIdNumber, card)
                .eq(TemporaryAdmissionBean::getType, BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType01)
                .orderByDesc(TemporaryAdmissionBean::getPersonId)
                .list();
        if(CollectionUtils.isNotEmpty(temporaryAdmissionBeanList)){
            return temporaryAdmissionBeanList.get(0).getPersonId();
        }

       return personManageService.getMaxPersonId();
    }
    
    /**
     * 修改人员临时准入信息
     *
     * @param dto 临时准入信息
     * @return 临时准入ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String updatePerson(TemporaryAdmissionPersonUpdateDTO dto) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = findOneById(dto.getObjId());

        if (StringUtils.isNotBlank(dto.getIdNumber()) && dto.getIdNumber().length() == 18) {
            Date birth = CardUtil.extractBirthDate(dto.getIdNumber());
            // 校验生日是否符合区间
            String msg = checkPersonAgeLimit(dto.getName(), birth);
            if (StringUtils.isNotBlank(msg)) {
                throw new GeneralSimpleException("400068", msg);
            }
        }
        
        ConstructionWorkAccessMonadBean accessMonadBean = null;
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getAccessMonadObjId())){
            accessMonadBean = constructionWorkAccessMonadService.findByObjId(temporaryAdmissionBean.getAccessMonadObjId());
        }
        if(Objects.nonNull(accessMonadBean)){

            // 审批中的单子无法编辑
            if(StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                throw new GeneralSimpleException("400059", String.valueOf(accessMonadBean.getApprovalNumber()));
            }else if(StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01)){
                // 已审批的单子，重新编辑，则只允许编辑授权日期和准入事由
                temporaryAdmissionBean.setCycleStart(dto.getCycleStart());
                temporaryAdmissionBean.setCycleEnd(dto.getCycleEnd());
                temporaryAdmissionBean.setRemark(dto.getRemark());
            }else{
                BeanUtils.copyProperties(dto, temporaryAdmissionBean);
            }
        }else{
            BeanUtils.copyProperties(dto, temporaryAdmissionBean);    
        }

        // 人员数字ID--临时准入人员ID要和人员表保持一致
        temporaryAdmissionBean.setPersonId(getPersonId(dto.getIdNumber()));

        boolean status = true;
        String accessMonadObjId = null;
        // 项目部单位
        boolean department = orgService.checkDepartment();
        if(department){
            // 项目部，编辑后，有审批单，则直接更新为已审核
            if(Objects.nonNull(accessMonadBean)){
                status = constructionWorkAccessMonadService.updateAccessStatusAndCycleStartAndCycleEndAndConstructionWorkObjIdByObjId(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01, temporaryAdmissionBean.getCycleStart(), temporaryAdmissionBean.getCycleEnd(), temporaryAdmissionBean.getConstructionWorkObjId(), accessMonadBean.getObjId());
            }else{
                accessMonadObjId = BaseCommonUtils.generateUUID();
                ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = new ConstructionWorkAccessMonadBean();
                constructionWorkAccessMonadBean.setObjId(accessMonadObjId);
                constructionWorkAccessMonadBean.setConstructionWorkObjId(temporaryAdmissionBean.getConstructionWorkObjId());
                constructionWorkAccessMonadBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03);
                constructionWorkAccessMonadBean.setAssociationObjId(temporaryAdmissionBean.getObjId());
                // 当前人员是项目部的人，则无需审批，直接通过
                constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);

                constructionWorkAccessMonadBean.setCycleStart(temporaryAdmissionBean.getCycleStart());
                constructionWorkAccessMonadBean.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
                constructionWorkAccessMonadBean.setCreateUserOrgId(BaseCommonUtils.extractOrdIdByToken());
                status = constructionWorkAccessMonadService.saveBean(constructionWorkAccessMonadBean);
            }
        }else{
            if(Objects.nonNull(accessMonadBean)){
                if(StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01)){
                    // 已核准的单子编辑后，改为未提交
                    status = constructionWorkAccessMonadService.updateAccessStatusByObjId(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus05, accessMonadBean.getObjId());
                }
            }
        }
        
        
        if(status){
            if(StringUtils.isBlank(temporaryAdmissionBean.getAccessMonadObjId())){
                temporaryAdmissionBean.setAccessMonadObjId(accessMonadObjId);
            }
            status = this.updateById(temporaryAdmissionBean);
            if(status){
                return temporaryAdmissionBean.getObjId();
            }
            log.error("人员临时准入审批单更新失败");
        }else{
            log.error("人员临时准入审批单状态更新失败");
        }

        throw new GeneralSimpleException("400063");
    }

    /**
     * 新增车辆临时准入信息
     *
     * @param dto 临时准入信息
     * @return 临时准入ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String insertCar(TemporaryAdmissionCarSaveDTO dto) throws GeneralSimpleException {

        // 项目部单位
        boolean department = orgService.checkDepartment();

        TemporaryAdmissionBean temporaryAdmissionBean = new TemporaryAdmissionBean();
        BeanUtils.copyProperties(dto, temporaryAdmissionBean);

        temporaryAdmissionBean.setOrgId(BaseCommonUtils.extractOrdIdByToken());
        
        // 车辆主键ID
        temporaryAdmissionBean.setObjId(BaseCommonUtils.generateUUID());
        // 审批单类型--车辆
        temporaryAdmissionBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType02);

        // 当前人员是项目部的人，则无需审批，直接通过
        boolean status = true;

        // 添加审批单-项目部直接通过
        String accessMonadObjId = null;
        if(department){
            accessMonadObjId = BaseCommonUtils.generateUUID();
            ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = new ConstructionWorkAccessMonadBean();
            constructionWorkAccessMonadBean.setObjId(accessMonadObjId);
            constructionWorkAccessMonadBean.setConstructionWorkObjId(temporaryAdmissionBean.getConstructionWorkObjId());
            constructionWorkAccessMonadBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04);
            constructionWorkAccessMonadBean.setAssociationObjId(temporaryAdmissionBean.getObjId());
            // 当前人员是项目部的人，则无需审批，直接通过
            constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);

            constructionWorkAccessMonadBean.setCycleStart(temporaryAdmissionBean.getCycleStart());
            constructionWorkAccessMonadBean.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
            constructionWorkAccessMonadBean.setCreateUserOrgId(BaseCommonUtils.extractOrdIdByToken());
            status = constructionWorkAccessMonadService.saveBean(constructionWorkAccessMonadBean);
        }

        if(status) {
            temporaryAdmissionBean.setAccessMonadObjId(accessMonadObjId);
            status = this.save(temporaryAdmissionBean);
            if (status) {
                return temporaryAdmissionBean.getObjId();
            }else{
                log.error("车辆临时准入信息保存失败");
            }
        }else{
            log.error("车辆临时准入审批单申请失败");
        }
        throw new GeneralSimpleException("400062");
    }

    /**
     * 更新车辆临时准入信息
     *
     * @param dto 临时准入信息
     * @return 临时准入ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public String updateCar(TemporaryAdmissionCarUpdateDTO dto) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = findOneById(dto.getObjId());

        ConstructionWorkAccessMonadBean accessMonadBean = null;
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getAccessMonadObjId())){
            accessMonadBean = constructionWorkAccessMonadService.findByObjId(temporaryAdmissionBean.getAccessMonadObjId());
        }
        if(Objects.nonNull(accessMonadBean)){

            // 审批中的单子无法编辑
            if(StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                throw new GeneralSimpleException("400059", String.valueOf(accessMonadBean.getApprovalNumber()));
            }else if(StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01)){
                // 已审批的单子，重新编辑，则只允许编辑授权日期和准入事由
                temporaryAdmissionBean.setCycleStart(dto.getCycleStart());
                temporaryAdmissionBean.setCycleEnd(dto.getCycleEnd());
                temporaryAdmissionBean.setRemark(dto.getRemark());
            }else{
                BeanUtils.copyProperties(dto, temporaryAdmissionBean);
            }
        }else{
            BeanUtils.copyProperties(dto, temporaryAdmissionBean);    
        }

        boolean status = true;
        String accessMonadObjId = null;
        // 项目部单位
        boolean department = orgService.checkDepartment();
        if(department){
            // 项目部，编辑后，有审批单，则直接更新为已审核
            if(Objects.nonNull(accessMonadBean)){
                status = constructionWorkAccessMonadService.updateAccessStatusAndCycleStartAndCycleEndAndConstructionWorkObjIdByObjId(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01, temporaryAdmissionBean.getCycleStart(), temporaryAdmissionBean.getCycleEnd(), temporaryAdmissionBean.getConstructionWorkObjId(), accessMonadBean.getObjId());
            }else{
                accessMonadObjId = BaseCommonUtils.generateUUID();
                ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = new ConstructionWorkAccessMonadBean();
                constructionWorkAccessMonadBean.setObjId(accessMonadObjId);
                constructionWorkAccessMonadBean.setConstructionWorkObjId(temporaryAdmissionBean.getConstructionWorkObjId());
                constructionWorkAccessMonadBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04);
                constructionWorkAccessMonadBean.setAssociationObjId(temporaryAdmissionBean.getObjId());
                // 当前人员是项目部的人，则无需审批，直接通过
                constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);

                constructionWorkAccessMonadBean.setCycleStart(temporaryAdmissionBean.getCycleStart());
                constructionWorkAccessMonadBean.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
                constructionWorkAccessMonadBean.setCreateUserOrgId(BaseCommonUtils.extractOrdIdByToken());
                status = constructionWorkAccessMonadService.saveBean(constructionWorkAccessMonadBean);
            }
        }else {
            if (Objects.nonNull(accessMonadBean)) {
                if (StringUtils.equals(accessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01)) {
                    // 已核准的单子编辑后，改为审核中
                    status = constructionWorkAccessMonadService.updateAccessStatusByObjId(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02, accessMonadBean.getObjId());
                }
            }
        }

        if(status) {
            if(StringUtils.isBlank(temporaryAdmissionBean.getAccessMonadObjId())){
                temporaryAdmissionBean.setAccessMonadObjId(accessMonadObjId);
            }
            status = this.updateById(temporaryAdmissionBean);
            if (status) {
                return temporaryAdmissionBean.getObjId();
            }else{
                log.error("车辆临时准入审批单更新失败");
            }
        }else{
            log.error("车辆临时准入审批单状态更新失败");
        }
        throw new GeneralSimpleException("400063");
    }

    /**
     * 临时准入分页查询
     *
     * @param dto 分页查询信息
     * @return 临时准入信息
     */
    @Override
    public IPage<TemporaryAdmissionPageVO> pageByTemporaryAdmission(TemporaryAdmissionPageDTO dto) throws GeneralSimpleException {

        // 总部管理员看全部
        // 项目部管理员，看自己所属工程
        // 参建单位人员看自己单位
        
        String orgId = BaseCommonUtils.extractOrdIdByToken();
        // 参建单位
        boolean participatingUnit = orgService.checkParticipatingUnit();
        List<String> accessMonadIdList;
        List<String> workIdList = Lists.newArrayList();
        if(participatingUnit){
            accessMonadIdList = null;
            boolean generalContractingUnit = userService.checkGeneralContractingUnit();
            if(generalContractingUnit){
                // 总包单位
                workIdList = constructionWorkService.findGeneralContractingUnitAccessWorkId();
            }else{
                // 参建单位成员
                workIdList = constructionWorkUnitRelaService.findWorkIdByUnitId(orgId);    
            }
            
            if(CollectionUtils.isEmpty(workIdList)){
                return new Page<>(dto.getPage(), dto.getSize());
            }
        }else if(orgService.checkDepartment()){
            // 项目部成员
            List<String> allDepartmentId = orgService.getDataPermissionDepartmentOrgId(orgId);
            boolean headOffice = userService.checkHeadOffice();
            if(headOffice){
                allDepartmentId = orgService.findAllDepartmentId();
            }
            if(CollectionUtils.isNotEmpty(allDepartmentId)){
                workIdList = constructionWorkService.findWorkIdByProjectDepartmentObjIdIn(allDepartmentId);
            }

            if(CollectionUtils.isEmpty(workIdList)){
                return new Page<>(dto.getPage(), dto.getSize());
            }

            List<String> typeList = Lists.newArrayList();
            typeList.add(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03);
            typeList.add(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04);

            accessMonadIdList = constructionWorkAccessMonadService.findObjIdByWorkIdInAndTypeInAndAccessStatus(workIdList, typeList, BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01);

            if(CollectionUtils.isEmpty(accessMonadIdList)){
                return new Page<>(dto.getPage(), dto.getSize());
            }
        } else {
            // 非参建单位和非项目部，直接退出
            return new Page<>(dto.getPage(), dto.getSize());
        }

        List<String> allAccessMonadIdList = null;
        if(StringUtils.isNotBlank(dto.getAccessStatus()) && !StringUtils.equals(dto.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus05)){
            List<String> typeList = Lists.newArrayList();
            typeList.add(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03);
            typeList.add(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04);
            allAccessMonadIdList = constructionWorkAccessMonadService.findObjIdByTypeInAndAccessStatus(typeList, dto.getAccessStatus());
            if(CollectionUtils.isEmpty(allAccessMonadIdList)){
                return new Page<>(dto.getPage(), dto.getSize());
            }
        }

        IPage<TemporaryAdmissionBean> queryPage = new Page<>(dto.getPage(), dto.getSize());

        IPage<TemporaryAdmissionBean> allPage = this.lambdaQuery()
                // 参建单位看自己部门的
                .eq(participatingUnit, TemporaryAdmissionBean::getOrgId, orgId)

                // 非参建单位，非总部管理员
                .and(!participatingUnit, 
                        w -> w.eq(TemporaryAdmissionBean::getOrgId, orgId)
                                .or()
                                .in(TemporaryAdmissionBean::getAccessMonadObjId, accessMonadIdList))

                // 姓名、车牌号
                .and(StringUtils.isNotBlank(dto.getSearchStr()), w -> w.like(TemporaryAdmissionBean::getName, dto.getSearchStr())
                        .or()
                        .like(TemporaryAdmissionBean::getIdNumber, dto.getSearchStr()))
                // 审批状态
                .in(CollectionUtils.isNotEmpty(allAccessMonadIdList), TemporaryAdmissionBean::getAccessMonadObjId, allAccessMonadIdList)
                .and(StringUtils.isNotBlank(dto.getAccessStatus()) && StringUtils.equals(dto.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus05), w -> w.isNull(TemporaryAdmissionBean::getAccessMonadObjId)
                        .or()
                        .eq(TemporaryAdmissionBean::getAccessMonadObjId, ""))

                // 准入日期
                .ge(Objects.nonNull(dto.getCycleStart()) && Objects.isNull(dto.getCycleEnd()), TemporaryAdmissionBean::getCycleEnd, dto.getCycleStart())

                .le(Objects.isNull(dto.getCycleStart()) && Objects.nonNull(dto.getCycleEnd()), TemporaryAdmissionBean::getCycleStart, dto.getCycleEnd())

                .and(Objects.nonNull(dto.getCycleStart()) && Objects.nonNull(dto.getCycleEnd()),
                        w -> w.or(z -> z.ge(TemporaryAdmissionBean::getCycleStart, dto.getCycleStart())
                                        .le(TemporaryAdmissionBean::getCycleStart, dto.getCycleEnd()))
                                .or(z -> z.ge(TemporaryAdmissionBean::getCycleEnd, dto.getCycleStart())
                                        .le(TemporaryAdmissionBean::getCycleEnd, dto.getCycleEnd()))
                                .or(z -> z.le(TemporaryAdmissionBean::getCycleStart, dto.getCycleStart())
                                        .ge(TemporaryAdmissionBean::getCycleEnd, dto.getCycleEnd())))

                // 按办理时间倒叙排列
                .orderByDesc(TemporaryAdmissionBean::getCreateTime)
                .orderByDesc(TemporaryAdmissionBean::getObjId)
                .page(queryPage);

        IPage<TemporaryAdmissionPageVO> pageVOIPage = new Page<>(allPage.getCurrent(), allPage.getSize(), allPage.getTotal());
        List<TemporaryAdmissionPageVO> pageVOList = Lists.newArrayList();
        List<TemporaryAdmissionBean> records = allPage.getRecords();
        if(CollectionUtils.isNotEmpty(records)){
            records.forEach(temporaryAdmissionBean -> pageVOList.add(beanToPageVO(temporaryAdmissionBean)));
            pageVOIPage.setRecords(pageVOList);
        }
        return pageVOIPage;
    }

    /**
     * 提交审核
     *
     * @param dto 审批单ID
     * @return 提交状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean submitReview(TemporaryAdmissionIdDTO dto) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = findOneById(dto.getObjId());
        
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getAccessMonadObjId())){
            // 存在审批单，则更新审批单状态
            ConstructionWorkAccessMonadBean workAccessMonadBean = constructionWorkAccessMonadService.findByObjId(temporaryAdmissionBean.getAccessMonadObjId());
            if(Objects.nonNull(workAccessMonadBean)){
                // 审批中和已审批无法提交审核
                if(StringUtils.equals(workAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01) ||
                        StringUtils.equals(workAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                    throw new GeneralSimpleException("400060");
                }
            }else{
                throw new GeneralSimpleException("400065");
            }

            return constructionWorkAccessMonadService.updateAccessStatusByObjId(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02, workAccessMonadBean.getObjId());
        }else{
            // 不存在审批单，则创建审批单
            String accessMonadObjId = BaseCommonUtils.generateUUID();
            ConstructionWorkAccessMonadBean constructionWorkAccessMonadBean = new ConstructionWorkAccessMonadBean();
            constructionWorkAccessMonadBean.setObjId(accessMonadObjId);
            constructionWorkAccessMonadBean.setConstructionWorkObjId(temporaryAdmissionBean.getConstructionWorkObjId());
            if(StringUtils.equals(temporaryAdmissionBean.getType(), BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType01)){
                constructionWorkAccessMonadBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03);
            }else if(StringUtils.equals(temporaryAdmissionBean.getType(), BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType02)){
                constructionWorkAccessMonadBean.setType(BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType04);
            }
           
            constructionWorkAccessMonadBean.setAssociationObjId(temporaryAdmissionBean.getObjId());
            // 当前人员是项目部的人，则无需审批，直接通过
            constructionWorkAccessMonadBean.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02);

            constructionWorkAccessMonadBean.setCycleStart(temporaryAdmissionBean.getCycleStart());
            constructionWorkAccessMonadBean.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
            constructionWorkAccessMonadBean.setCreateUserOrgId(BaseCommonUtils.extractOrdIdByToken());
            boolean status = constructionWorkAccessMonadService.saveBean(constructionWorkAccessMonadBean);
            
            if(status){
                temporaryAdmissionBean.setAccessMonadObjId(accessMonadObjId);
                return updateById(temporaryAdmissionBean);
            }
            throw new GeneralSimpleException("400066");
        }
    }

    /**
     * 撤回
     *
     * @param dto 审批单ID
     * @return 撤回状态
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean withdraw(TemporaryAdmissionIdDTO dto) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = findOneById(dto.getObjId());
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getAccessMonadObjId())){
            ConstructionWorkAccessMonadBean workAccessMonadBean = constructionWorkAccessMonadService.findByObjId(temporaryAdmissionBean.getAccessMonadObjId());
            if(Objects.nonNull(workAccessMonadBean)){
                // 审批中和已审批无法提交审核
                if(!StringUtils.equals(workAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus02)){
                    throw new GeneralSimpleException("400061");
                }

                return constructionWorkAccessMonadService.updateAccessStatusByObjId(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus04, workAccessMonadBean.getObjId());
            }
        }
        
        return false;
    }

    /**
     * 查询人员临时准入信息
     *
     * @param dto 审批单ID
     * @return 临时准入信息
     */
    @Override
    public TemporaryAdmissionPersonBaseVO findByPerson(TemporaryAdmissionIdDTO dto) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = findOneById(dto.getObjId());
        TemporaryAdmissionPersonBaseVO personBaseVO = new TemporaryAdmissionPersonBaseVO();
        BeanUtils.copyProperties(temporaryAdmissionBean, personBaseVO);
        
        return personBaseVO;
    }

    /**
     * 查询车辆临时准入信息
     *
     * @param dto 审批单ID
     * @return 临时准入信息
     */
    @Override
    public TemporaryAdmissionCarBaseVO findByCar(TemporaryAdmissionIdDTO dto) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = findOneById(dto.getObjId());
        TemporaryAdmissionCarBaseVO carBaseVO = new TemporaryAdmissionCarBaseVO();
        BeanUtils.copyProperties(temporaryAdmissionBean, carBaseVO);

        return carBaseVO;
    }

    /**
     * 根据用户ID查询用户详细信息
     *
     * @param personIdList 用户ID
     * @param workId     工程ID
     * @return 用户详细信息
     */
    @Override
    public List<PersonSyncDetailInfoVO> findByPersonIdInAndWorkId(List<String> personIdList, String workId) {
        // 根据工程和人员ID，查询人员详细信息
        List<TemporaryAdmissionBean> temporaryAdmissionBeanList = this.lambdaQuery()
                .in(TemporaryAdmissionBean::getPersonId, personIdList)
                .list();
        List<PersonSyncDetailInfoVO> detailInfoVOList = Lists.newArrayList();
        if(CollectionUtils.isNotEmpty(temporaryAdmissionBeanList)){
            List<String> personObjIdList = temporaryAdmissionBeanList.stream().map(TemporaryAdmissionBean::getObjId).collect(Collectors.toList());
            // 查询人员中，哪些是审批通过的，并且在有效时间内
            Date date = DateUtil.beginOfDay(DateUtil.date());
            personObjIdList = constructionWorkAccessMonadService.findPersonObjIdByAssociationObjIdInAndTypeAndAccessStatus(personObjIdList, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType03, BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus01, date);
            if(CollectionUtils.isEmpty(personObjIdList)){
                return detailInfoVOList;
            }

            // 重新查询用户信息
            temporaryAdmissionBeanList = this.lambdaQuery().in(TemporaryAdmissionBean::getObjId, personObjIdList).list();

            List<String> cardList = temporaryAdmissionBeanList.stream().map(TemporaryAdmissionBean::getIdNumber).filter(StringUtils::isNotBlank).collect(Collectors.toList());
            List<String> blacklistPersonIdList = Lists.newArrayList();
            if(CollectionUtils.isNotEmpty(cardList)){
                blacklistPersonIdList = blacklistService.findBlacklistByIdNumberInAndType(personIdList, BaseCodeConstants.CodeType_ApprovalFormType.KEY_ApprovalFormType01);
            }
          
            blacklistPersonIdList = blacklistPersonIdList == null ? Lists.newArrayList() : blacklistPersonIdList;
            List<String> finalBlacklistPersonIdList = blacklistPersonIdList;

            // 去重，用户可能存在多个临时准入，需要做排除
            List<Integer> existPersonIdList = Lists.newArrayList();
            temporaryAdmissionBeanList.forEach(temporaryAdmissionBean -> {
                if(existPersonIdList.contains(temporaryAdmissionBean.getPersonId())){
                   return; 
                }
                PersonSyncDetailInfoVO detailInfoVO = new PersonSyncDetailInfoVO();
                detailInfoVO.setPerson_id(String.valueOf(temporaryAdmissionBean.getPersonId()));
                detailInfoVO.setId_card(temporaryAdmissionBean.getIdNumber());
                detailInfoVO.setPerson_name(temporaryAdmissionBean.getName());

                if(StringUtils.isNotBlank(temporaryAdmissionBean.getIdNumber())){
                    detailInfoVO.setPerson_type(finalBlacklistPersonIdList.contains(temporaryAdmissionBean.getIdNumber()) ? MqttEnum.PersonType.BLACKLIST.getKey() : MqttEnum.PersonType.WHITE_LIST.getKey());
                }else{
                    detailInfoVO.setPerson_type(MqttEnum.PersonType.WHITE_LIST.getKey());
                }

                // 性别
//                int sex = 0;
//                if(StringUtils.isNotBlank(personManageBean.getSex())){
//                    sex = Integer.parseInt(personManageBean.getSex());
//                }
//                detailInfoVO.setSex(sex);
//
//                // 生日
//                if(Objects.nonNull(personManageBean.getBirth())){
//                    detailInfoVO.setBirthday(BaseCommonUtils.DATE_FORMAT_DAY_3.format(personManageBean.getBirth()));
//                }
                if(StringUtils.isNotBlank(temporaryAdmissionBean.getProfilePicture())){
                    detailInfoVO.setTemplateImgUrl(Collections.singletonList(attachmentService.findStaticImagePath(temporaryAdmissionBean.getProfilePicture())));
                }
                
                // 准入期限
                if(Objects.nonNull(temporaryAdmissionBean.getCycleStart())){
                    Date cycleStart = temporaryAdmissionBean.getCycleStart();
                    String dateStr = BaseCommonUtils.DATE_FORMAT_DAY_3.format(cycleStart);
                    String timeStr = BaseCommonUtils.DATE_FORMAT_HOUR_MI_SECOND.format(cycleStart);
                    detailInfoVO.setThroughDateFrom(dateStr + " ");
                    detailInfoVO.setThroughMomentFrom(timeStr);
                }

                if(Objects.nonNull(temporaryAdmissionBean.getCycleEnd())){
                    Date cycleEnd = temporaryAdmissionBean.getCycleEnd();
                    String dateStr = BaseCommonUtils.DATE_FORMAT_DAY_3.format(cycleEnd);
                    String timeStr = BaseCommonUtils.DATE_FORMAT_HOUR_MI_SECOND.format(cycleEnd);
                    detailInfoVO.setThroughDateTo(dateStr + " ");
                    detailInfoVO.setThroughMomentTo(timeStr);
                }

                detailInfoVOList.add(detailInfoVO);
                existPersonIdList.add(temporaryAdmissionBean.getPersonId());
            });
        }

        return detailInfoVOList;
    }

    /**
     * 查询可办理准入的在建工程
     *
     * @return 工程信息
     */
    @Override
    public List<ConstructionWorkListVO> getWorkList() throws GeneralSimpleException {
        List<ConstructionWorkListVO> workListVOList = null;
        if(orgService.checkDepartment()){
            workListVOList = constructionWorkService.findDepartmentPendingAdmissionList();
        }else if(orgService.checkParticipatingUnit()){
            workListVOList = constructionWorkService.findParticipatingUnitPendingAdmissionList();
        }
        return workListVOList;
    }

    /**
     * 查询存在的准入
     *
     * @param dto 查询条件
     * @return 准入信息
     */
    @Override
    public List<TemporaryAdmissionCheckWorkVO> findWorkAccess(TemporaryAdmissionWorkDTO dto) {
        List<TemporaryAdmissionCheckWorkVO> checkWorkVOList = Lists.newArrayList();
        List<TemporaryAdmissionBean> temporaryAdmissionBeanList = this.lambdaQuery().eq(TemporaryAdmissionBean::getIdNumber, dto.getIdNumber())
                .eq(TemporaryAdmissionBean::getConstructionWorkObjId, dto.getConstructionWorkObjId())
                .ne(StringUtils.isNotBlank(dto.getObjId()), TemporaryAdmissionBean::getObjId, dto.getObjId())
                .list();
        if(CollectionUtils.isNotEmpty(temporaryAdmissionBeanList)){
            temporaryAdmissionBeanList.forEach(temporaryAdmissionBean -> {
                TemporaryAdmissionCheckWorkVO checkWorkVO = new TemporaryAdmissionCheckWorkVO();
                checkWorkVO.setIfTemporary(BaseCodeConstants.CodeType_WhetherCode.KEY_WhetherCode01);
                checkWorkVO.setCycleStart(temporaryAdmissionBean.getCycleStart());
                checkWorkVO.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
                checkWorkVOList.add(checkWorkVO);
            });
        }

        // 查询正式准入
        checkWorkVOList.addAll(personManageService.findWorkAccess(dto.getIdNumber(), dto.getConstructionWorkObjId()));

        return checkWorkVOList;
    }

    /**
     * 根据身份证号查询人员ID
     *
     * @param card 身份证号
     * @return 人员ID
     */
    @Override
    public Integer findIdByCard(String card) {
        TemporaryAdmissionBean temporaryAdmissionBean = this.lambdaQuery().eq(TemporaryAdmissionBean::getIdNumber, card)
                .eq(TemporaryAdmissionBean::getType, BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType01)
                .last(Constants.LAST_SQL).one();
        if(Objects.nonNull(temporaryAdmissionBean)){
            return temporaryAdmissionBean.getPersonId();
        }
        return null;
    }

    /**
     * 更新审批单的准入周期
     *
     * @param cycleStart       开始准入
     * @param cycleEnd         结束准入
     * @param associationObjId 临时准入ID
     */
    @Override
    @Transactional(value = "transactionManager", propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateCycleByObjId(Date cycleStart, Date cycleEnd, String associationObjId) {
        TemporaryAdmissionBean temporaryAdmissionBean = this.getById(associationObjId);
        if(Objects.nonNull(temporaryAdmissionBean)){
            boolean isSave = false;
            if(Objects.nonNull(cycleStart)){
                temporaryAdmissionBean.setCycleStart(cycleStart);
                isSave = true;
            }

            if(Objects.nonNull(cycleEnd)){
                temporaryAdmissionBean.setCycleEnd(cycleEnd);
                isSave = true;
            }
            
            if(isSave){
                this.updateById(temporaryAdmissionBean);
            }
        }
    }

    /**
     * 实体转分页对象
     * @param temporaryAdmissionBean 临时准入
     * @return 分页对象
     */
    private TemporaryAdmissionPageVO beanToPageVO(TemporaryAdmissionBean temporaryAdmissionBean){
        TemporaryAdmissionPageVO pageVO = new TemporaryAdmissionPageVO();
        
        pageVO.setObjId(temporaryAdmissionBean.getObjId());
        pageVO.setCreateTime(temporaryAdmissionBean.getCreateTime());
        pageVO.setConstructionWorkObjId(temporaryAdmissionBean.getConstructionWorkObjId());
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getConstructionWorkObjId())){
            pageVO.setConstructionWorkName(constructionWorkService.findNameByObjId(temporaryAdmissionBean.getConstructionWorkObjId()));
        }
      
        // 准入类型
        pageVO.setType(temporaryAdmissionBean.getType());
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getType())){
            if(StringUtils.equals(temporaryAdmissionBean.getType(), BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType01)){
                // 人员，返回姓名
                pageVO.setName(temporaryAdmissionBean.getName());
            }else if(StringUtils.equals(temporaryAdmissionBean.getType(), BaseCodeConstants.CodeType_AdmissionType.KEY_AdmissionType02)){
                // 车辆，返回车牌号
                pageVO.setName(temporaryAdmissionBean.getIdNumber());
            }
        }
        
        pageVO.setCycleStart(temporaryAdmissionBean.getCycleStart());
        pageVO.setCycleEnd(temporaryAdmissionBean.getCycleEnd());
        pageVO.setRemark(temporaryAdmissionBean.getRemark());
        
        if(StringUtils.isNotBlank(temporaryAdmissionBean.getAccessMonadObjId())){
            ConstructionWorkAccessMonadBean workAccessMonadBean = constructionWorkAccessMonadService.findByObjId(temporaryAdmissionBean.getAccessMonadObjId());
            if(Objects.nonNull(workAccessMonadBean)){
                pageVO.setAccessStatus(workAccessMonadBean.getAccessStatus());
                if(StringUtils.equals(workAccessMonadBean.getAccessStatus(), BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus03)){
                    pageVO.setOpinion(workAccessMonadBean.getOpinion());
                }
            }else{
                pageVO.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus05);
            }
        }else{
            pageVO.setAccessStatus(BaseCodeConstants.CodeType_AccessStatus.KEY_AccessStatus05);    
        }
        
        return pageVO;
    }
    
    /**
     * 查询临时准入单
     * @param objId 临时准入ID
     * @return 临时准入信息
     */
    private TemporaryAdmissionBean findOneById(String objId) throws GeneralSimpleException {
        TemporaryAdmissionBean temporaryAdmissionBean = this.getById(objId);
        if(Objects.isNull(temporaryAdmissionBean)){
            throw new GeneralSimpleException("400057", objId);
        }
        return temporaryAdmissionBean;
    }
}
